package cn.tworice.client.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CountryResponse;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;


@Service
public class NetworkService {
    public long getSpeed(String targetURL) throws IOException {
        long startTime = System.currentTimeMillis();
        URL url = new URL(targetURL);
        URLConnection connection = url.openConnection();
        connection.connect();
        long endTime = System.currentTimeMillis();
        return endTime - startTime;
    }

    public long getDelay() throws IOException {
        InetAddress address = InetAddress.getByName("www.baidu.com");
        long startTime = System.nanoTime();
        if (address.isReachable(5000)) {
            long endTime = System.nanoTime();
            long duration = (endTime - startTime) / 1000000;
            return duration;
        } else {
            throw new RuntimeException("Host is not reachable");
        }
    }

    /**
     * 检测当前URL连接是否安全
     * @param url 地址
     * @return boolean
     * @author 二饭 [2023/4/1]
     **/
    public String isConnectionSecure(String url) {
        try {
            if(!url.startsWith("http")){
                url="http://"+url;
            }

            // 创建一个信任所有自签名证书的SSL上下文
            SSLContext sslContext = SSLContexts.custom()
                    .loadTrustMaterial(new TrustSelfSignedStrategy())
                    .build();

            // 创建一个允许自签名证书的SSL连接工厂
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"},
                    null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

            // 使用SSL连接工厂创建一个HTTP客户端
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();

            // 创建一个HttpGet请求
            HttpGet httpGet = new HttpGet(url);

            // 发送请求并获取响应
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                if (response.getStatusLine().getStatusCode() == 200) {
                    EntityUtils.consume(entity);
                    return url+"域名安全";
                } else {
                    EntityUtils.consume(entity);
                    throw new RuntimeException("连接失败，状态码: " + response.getStatusLine().getStatusCode());
                }
            } catch (SSLPeerUnverifiedException e) {
                throw new RuntimeException("SSL证书无效: " + e.getMessage());
            }
        } catch (IOException e) {
            throw new RuntimeException("网络连接错误: " + e.getMessage());
        } catch (KeyStoreException e) {
            throw new RuntimeException("KeyStore错误: " + e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("不支持的算法: " + e.getMessage());
        } catch (KeyManagementException e) {
            throw new RuntimeException("密钥管理错误: " + e.getMessage());
        }
    }

    /**
     * 获取域名
     * @param ipAddr
     * @return java.lang.String
     * @author 二饭 [2023/4/1]
     **/
    public String getHostName(String ipAddr){
        try {
            String ipAddress = "8.140.131.83";
            InetAddress inetAddress = InetAddress.getByName(ipAddress);
            return inetAddress.getHostName();
        } catch (UnknownHostException e) {
            throw  new RuntimeException("无法解析IP地址: " + e.getMessage());
        }
    }


    /**
     * 获取当前连接的Wi-Fi SSID（名称）
     * @return java.lang.String
     * @author 二饭 [2023/4/1]
     **/
    public   String getCurrentWiFiSSID() throws IOException {
        ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "netsh wlan show interfaces");
        Process process = processBuilder.start();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains("SSID")) {
                    return line.split(":")[1].trim();
                }
            }
        }
        return null;
    }

    /**
     * 检查Wi-Fi的认证方式
     * @param ssid
     * @return boolean
     * @author 二饭 [2023/4/1]
     **/
    public boolean isWiFiSecure(String ssid) throws IOException {
        ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "netsh wlan show networks mode=bssid");
        Process process = processBuilder.start();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            boolean ssidFound = false;
            while ((line = reader.readLine()) != null) {
                if (line.contains("SSID " + ssid)) {
                    ssidFound = true;
                } else if (ssidFound && line.contains("Authentication")) {
                    String authentication = line.split(":")[1].trim();
                    return !"Open".equalsIgnoreCase(authentication);
                }
            }
        }
        return false;
    }


    /**
     * 对比本地DNS和DNS服务器的DNS服务器比较判断是否被劫持
     * @param domainToCheck
     * @return java.lang.String
     * @author 二饭 [2023/4/13]
     **/
    public String dns(String domainToCheck) {
        List<String> trustedDnsServers = Arrays.asList("8.8.8.8", "8.8.4.4", "208.67.222.222", "208.67.220.220");

        try {
            InetAddress[] localResolvedAddress = InetAddress.getAllByName(domainToCheck);

            for (String dnsServer : trustedDnsServers) {
                InetAddress[] dnsResolvedAddress = this.getInetAddressByDnsServer(domainToCheck, dnsServer);
                if (dnsResolvedAddress != null && !this.isSame(dnsResolvedAddress,localResolvedAddress)) {
                    return "DNS服务器 " + dnsServer + " 解析的IP地址与本地解析的IP地址不同: " + this.getIpString(dnsResolvedAddress);
                }
            }
            return "未检测到DNS劫持";
        } catch (UnknownHostException e) {
            throw new RuntimeException("无法解析域名: " + e.getMessage());
        }
    }

    private InetAddress[] getInetAddressByDnsServer(String domain, String dnsServer) throws UnknownHostException {
        Security.setProperty("networkaddress.cache.ttl", "0");
        System.setProperty("sun.net.spi.nameservice.nameservers", dnsServer);
        System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
        return InetAddress.getAllByName(domain);
    }

    private boolean isSame(InetAddress[] a,InetAddress[] b){
        for (InetAddress address : a) {
            boolean state = false;
            for(InetAddress address2 : b){
                if(address.equals(address2)){
                    state = true;
                }
            }
            if(!state){
                return false;
            }
        }
        return true;
    }

    private String getIpString(InetAddress[] inetAddresses){
        String result = "";
        for (InetAddress inetAddress : inetAddresses) {
            result += inetAddress.getHostAddress() + " ";
        }
        return result;
    }



    /**
     * 通过调用getAllByName()方法获取example.com域名的所有IP地址，
     * 并与预期的IP地址进行比较。
     * 如果返回的IP地址与预期的IP地址不一致，
     * 则输出可能存在域名劫持的提示信息。
     * @return void
     * @author 二饭 [2023/4/13]
     **/
    public List<String> getIPAddrByName(String domain) throws UnknownHostException {
        List<String> list = new ArrayList<>();
        InetAddress[] addresses = InetAddress.getAllByName(domain);
        for (InetAddress address : addresses) {
            list.add(address.getHostAddress());
        }
        return list;
    }

    /**
     * 获取域名
     * @param urlString
     * @return java.lang.String
     * @author 二饭 [2023/4/13]
     **/
    public String parseDomain(String urlString) throws MalformedURLException {
        if(!urlString.startsWith("http")){
            urlString = "http://" + urlString;
        }
        URL url = new URL(urlString);
        return url.getHost();
    }


    File database = new File(System.getProperty("user.dir")+"\\src\\main\\resources\\static\\Country.mmdb");
    /**
     * 通过IP获取归属地
     * @param ip IP地址
     * @return java.lang.String
     * @author 二饭 [2023/4/13]
     **/
    public String getCountryName(String ip) throws IOException, GeoIp2Exception {
        DatabaseReader reader = new DatabaseReader.Builder(database).build();

        InetAddress ipAddress = InetAddress.getByName(ip);

        CountryResponse country = reader.country(ipAddress);
        JSONObject jsonObject = JSON.parseObject(country.toJson());
        return jsonObject.getJSONObject("country").getJSONObject("names").getString("zh-CN");
    }
}
